home *** CD-ROM | disk | FTP | other *** search
- char *ckxv = "Data General tty I/O, 5A(098) 10 May 93";
-
- /* C K D T I O */
-
- /* C-Kermit interrupt, terminal control & i/o functions for DG AOS/VS */
-
- /*
- Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
- Columbia University Academic Information Systems, New York City.
-
- Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
- York. The C-Kermit software may not be, in whole or in part, licensed or
- sold for profit as a software product itself, nor may it be included in or
- distributed with commercial products or otherwise distributed by commercial
- concerns to their clients or customers without written permission of the
- Office of Kermit Development and Distribution, Columbia University. This
- copyright notice must not be removed, altered, or obscured.
-
- This module originally adapted to the Data General computers by:
- Phil Julian, SAS Institute, Inc., Box 8000, Cary, NC 27512-8000.
- Adapted to C-Kermit 5A by Eugenia Harris of Data General.
- */
- #define MAXINBUF 2048 /* See ckdcon.c for same definition. */
- #nolist
- #include <memory.h>
- #include <string.h>
- #include <dglib.h>
- #include <bit.h>
- #include <sysid.h>
- #include <sys_calls.h>
- #include <packets/normal_io.h>
- #include <multitask.h>
- #include <paru.h>
- #include <stdio.h>
- #include <packets:common.h>
- #include <packets:characteristics.h>
- #list
- #define CONINT_TSK 20 /* Task id of interrupt-checker */
- #define CONINT_PRI 0 /* Same as calling task */
- #define CONINT_STACK 02000
- int con_reads_mt = 0; /* Flag if task is active */
- int conint_ch; /* MT character read */
- int conint_avl; /* Flag that char available */
- int termtype;
- /* Delimiter table -- defaults to CR only */
- short idel_tbl[7] = {0x4,0,0,0,0,0,0};
- #include <stdio.h> /* Unix Standard i/o */
-
- #ifndef DEVNAMLEN
- #define DEVNAMLEN (L_ctermid + 6)
- #endif
-
- #ifdef NETCONN
- #undef DEVNAMLEN
- #define DEVNAMLEN 50 /* longer field for host:service */
- #endif /* NETCONN */
-
- #include <sys/dir.h> /* Directory */
- #include <ctype.h> /* Character types */
-
- /* Maximum length for the name of a tty device */
- #ifndef DEVNAMLEN
- #define DEVNAMLEN 25
- #endif
-
- #include <stdio.h> /* Unix Standard i/o */
- #include <signal.h> /* Interrupts */
- #include <setjmp.h> /* Longjumps */
- #include "ckcdeb.h" /* Typedefs, formats for debug() */
- #include "ckcnet.h"
- #include <sys/stat.h>
-
- #ifdef datageneral
- char *ckxsys = " Data General AOS/VS";
- #endif
-
- /* Features... */
-
- #define MYREAD
-
- /*
- Variables available to outside world:
-
- dftty -- Pointer to default tty name string, like "/dev/tty".
- dfloc -- 0 if dftty is console, 1 if external line.
- dfprty -- Default parity
- dfflow -- Default flow control
- ckxech -- Flag for who echoes console typein:
- 1 - The program (system echo is turned off)
- 0 - The system (or front end, or terminal).
- functions that want to do their own echoing should check this flag
- before doing so.
-
- flfnam -- Name of lock file, including its path, e.g.,
- "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
- haslock -- Flag set if this kermit established a uucp lock.
- inbufc -- number of tty line rawmode unread characters
- (system III/V unixes)
- backgrd -- Flag indicating program executing in background ( & on
- end of shell command). Used to ignore INT and QUIT signals.
-
- /* Declarations of variables global within this module */
-
- static time_t tcount; /* Elapsed time counter */
- SIGTYP (*saval)() = NULL; /* For saving alarm handler */
-
- /* The following lists of functions are somewhat out of date. For a
- better listing, see ckutio.c
-
- Functions for assigned communication line (either external or console tty):
-
- sysinit() -- System dependent program initialization
- ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
- ttclos() -- Close & reset the tty, releasing any access lock.
- ttpkt(speed,flow,parity)-- Put the tty in packet mode and set the speed.
- ttvt(speed,flow) -- Put the tty in virtual terminal mode.
- or in DIALING or CONNECTED modem control state.
- ttinl(dest,max,timo,eol,start) -- Timed read line from the tty.
- ttinc(timo) -- Timed read character from tty.
- myread() -- System 3 raw mode bulk buffer read, gives
- -- subsequent chars one at a time and simulates
- -- FIONREAD!
- ttchk() -- See how many characters in tty input buffer.
- ttxin(n,buf) -- Read n characters from tty (untimed).
- ttol(string,length) -- Write a string to the tty.
- ttoc(c) -- Write a character to the tty.
- ttflui() -- Flush tty input buffer.
- ttfluo() -- Flush tty output buffer. (not used)
- ttgmdm() -- Returns status of modem signals (not used)
- ttgspd() -- Returns speed of tty line
- ttsspd(cps) -- Set line speed on tty line
- ttimoff() -- Turns off all pending timer interrupts
- ttscarr(carrier) -- Copies argument to global variable
- ttwmdm(mdmsig,timo) -- Wait for specified signal (not used)
- ttlock(ttname) -- Lock against uucp collisions (not used)
- ttunlck() -- Unlock " " " (not used)
- look4lk(ttname) -- Check if a lock file exists (not used)
-
- Functions for console terminal:
-
- congm() -- Get console terminal modes.
- concb(esc) -- Put the console in single-character wakeup mode with no echo.
- conbin(esc) -- Put the console in binary (raw) mode.
- conres() -- Restore the console to mode obtained by congm().
- conoc(c) -- Unbuffered output, one character to console.
- conol(s) -- Unbuffered output, null-terminated string to the console.
- conola(s) -- Unbuffered output, array of strings to the console.
- conxo(n,s) -- Unbuffered output, n characters to the console.
- conchk() -- Check if characters available at console (bsd 4.2).
-
- Check if escape char (^\) typed at console (System III/V).
- coninc(timo) -- Timed get a character from the console.
- conint() -- Enable terminal interrupts on the console if not background.
- connoi() -- Disable terminal interrupts on the console if not background.
- congks(timo) -- Get keyboard scan code (not used)
-
- Time functions:
-
- msleep(m) -- Millisecond sleep
- ztime(&s) -- Return pointer to date/time string
- rtimer() -- Reset timer
- gtimer() -- Get elapsed time since last call to rtimer()
- */
-
- /* System III, System V */
-
- #ifdef UXIII
- #ifdef datageneral
- /* Console and terminal characteristics vectors */
- short *charcurr;
- short charconin[$CLMAX]; /* Console input; channel 0 */
- short charconout[$CLMAX]; /* Console output; channel 1 */
- short chartty[$CLMAX]; /* generic tty channel */
- short charttyin[$CLMAX]; /* tty input; channel ttyfd */
- short charttyout[$CLMAX]; /* tty output; channel ttyfdout */
- short ch_ttold[$CLMAX];
- short ch_ttraw[$CLMAX];
- short ch_ttvt[$CLMAX];
- short ch_ccold[$CLMAX];
- short ch_ccraw[$CLMAX];
- short ch_ccbrk[$CLMAX];
- #undef ECHO
- #include <sys/termio.h>
- /* Add synonymns for Unix type ioctl */
- #define TCSETAF TCSETA
- #define TCSETAW TCSETA
- #else
- #include <termio.h>
- #include <sys/ioctl.h>
- #endif datageneral
-
- #include <fcntl.h> /* directory reading for locking */
- #include <errno.h> /* error numbers for system returns */
- #endif
-
- /* Declarations */
-
- long time(); /* All Unixes should have this... */
- extern int errno; /* System call error return */
- extern int ttnproto;
- extern int ttnet;
- extern int xfrcan, xfrchr, xfrnum; /* Transfer cancellation */
-
- /* dftty is the device name of the default device for file transfer */
- /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
-
- char *dftty = CTTNAM; /* Remote by default, use normal */
- int dfloc = 0; /* controlling terminal name. */
- int dfprty = 0; /* Parity (0 = none) */
- int dfflow = 1; /* Xon/Xoff flow control */
- int backgrd = 0; /* Assume in foreground (no '&' ) */
- int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
-
- /* Declarations of variables global within this module */
-
- static long tcount; /* Elapsed time counter */
- static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */
- static jmp_buf sjbuf, jjbuf; /* Longjump buffer */
-
- static int lkf = 0, /* Line lock flag */
- conif = 0, /* Console interrupts on/off flag */
- cgmf = 0, /* Flag that console modes saved */
- xlocal = 0; /* Flag for tty local or remote */
- curcarr = 0; /* Carrier mode: require/ignore. */
- int ttyfd = -1; /* TTY file descriptor */
- int tvtflg = 0;
- long ttspeed = -1; /* For saving speed */
- int ttflow = -9; /* For saving flow */
- int ttld = -1; /* Line discipline */
- int ttfdflg = 0;
- int ttpmsk = 0377;
- int ttprty = 0;
- int ttpflg = 0; /* Parity not sensed yet */
- int ttmdm = 0;
- int ttcarr = CAR_AUT; /* Carrier handling mode. */
- int telnetfd = 0;
- static int netconn = 0;
- int fdflag = 0;
- static char escchr; /* Escape or attn character */
- static int kerld = 0; /* Not selected, no special l.d. */
- int x25fd = 0;
-
- #ifdef UXIII
- static struct termio /* sgtty info... */
- ttold, ttraw, tttvt, /* for communication line */
- ccold, ccraw, cccbrk; /* and for console */
- #else
- static struct sgttyb /* sgtty info... */
- ttold, ttraw, tttvt, ttbuf, /* for communication line */
- ccold, ccraw, cccbrk; /* and for console */
- #endif
-
- char flfnam[80]; /* uucp lock file path name */
- int haslock = 0; /* =1 if this kermit locked uucp */
-
- static int inbufc = 0; /* stuff for efficient SIII raw line */
- static int ungotn = -1; /* pushback to unread character */
- static int conesc = 0; /* set to 1 if esc char (^\) typed */
-
- static int ttlock(); /* definition of ttlock subprocedure */
- static int ttunlck(); /* and unlock subprocedure */
- static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */
-
- #ifdef datageneral
- FILE *ttfile,*ttfileout; /* Files opened by ttopen */
-
- struct p_nio_ex w_io_parms; /* ?write system call structure */
- struct p_nio_ex r_io_parms; /* ?read system call structure */
-
- struct p_nio_ex io_parms; /* open structure in ttopen */
- struct p_nio_ex x_io_parms; /* ?read/?write structure for ttyfd */
- struct p_nio_ex xout_parms; /* ?write structure for ttyfdout */
- struct p_screen x_io_scrn,
- r_io_scrn,io_screen; /* Edit-read structures */
-
- int ttyfdout = -1; /* ?write Unix number for remote out */
- short timotty = 0; /* {Flag for timeouts (=1), value */
- short timocon = 0; /* tty is ttyfd..., con is Unix 0/1 */
- extern char *SPACMD; /* returns space in CURRENT dir */
- #endif
-
- /* Timeout handler for communication line input functions */
-
- SIGTYP
- timerh(foo) int foo; { /* we will try to use this */
- ttimoff();
- longjmp(sjbuf,1);
- }
-
- /* Control-C trap for communication line input functions */
- /* These are not used in the VS implementation. Instead, there is a task */
- /* called conint_mt that reads characters from the keyboard and sets a */
- /* flag when it gets one. It is then up to other routines (e.g., chkint()*/
- /* to determine what to do with the characters (and zero the flag) --ENH */
-
- int cc_int; /* Flag */
- SIGTYP (* occt)(); /* For saving old SIGINT handler */
-
- SIGTYP
- cctrap(foo) int foo; { /* Needs arg for ANSI C */
- cc_int = 1; /* signal() prototype. */
- return;
- }
-
- /* S Y S I N I T -- System-dependent program initialization. */
-
- int
- sysinit() {
-
- #ifdef datageneral
- /* Set up many things on the DG system, for initialization, etc. */
-
- short flags[3];
- char *username;
- int err;
-
- signal(SIGALRM,SIG_IGN);
-
- /* Get the terminal type, since DG terminals are different from others,
- especially in the way BS is handled ('\b' is EM).
- termtype = 0 means a regular DG style terminal, and
- termtype = 1 means an ANSI style terminal with ^H for backspace.
- If Kermit is run in batch or has redirected input, then we do not
- want to test or set the console characteristics.
- */
- termtype = 0;
- if (isatty(0)) {
- if (sys_gchr(channel(0),1<<31,&flags))
- { perror("sysinit: sys_gchr: "); return(1); }
-
- /* Only determine whether or not it is a $TTY */
- if ((flags[1] & $DTYPE) == $TTY) termtype = 1;
- }
-
- zero((char *) &w_io_parms, sizeof(w_io_parms));
- w_io_parms.ich = channel(1); /* stdout */
- w_io_parms.isti = $IBIN|$RTDS|$ICRF|$OFOT;
- w_io_parms.isti &= ~$IPST;
- w_io_parms.imrs = MAXINBUF-1;
- w_io_parms.ibad = -1;
- w_io_parms.ircl = -1;
-
- zero((char *) &r_io_parms, sizeof(r_io_parms));
- r_io_parms.ich = channel(0); /* stdin */
- r_io_parms.isti = $IBIN|$RTFX|$ICRF|$OFIN;
- r_io_parms.isti &= ~$IPST;
- r_io_parms.imrs = MAXINBUF-1;
- r_io_parms.ibad = -1;
- r_io_parms.ircl = -1;
-
- zero((char *) &r_io_scrn, sizeof(r_io_scrn));
- r_io_parms.etsp = 0; /* Screen management extension */
- r_io_scrn.esfc &= ~$ESNE; /* Echo input data */
- r_io_scrn.esfc &= ~$ESSE; /* No screen edit */
- r_io_scrn.esfc |= $ESGT; /* Dump ring buffer */
-
- zero((char *) &x_io_parms, sizeof(x_io_parms));
- /* $RTDY must be used instead of $RTDS since this causes failure on
- * the Prime, which is probably getting data overruns on output or
- * missing data. Also, $RTDY is more efficient and faster.
- */
- x_io_parms.isti = $IBIN|$RTFX|$ICRF|$OFIO|$IPKL;
- x_io_parms.isti &= ~$IPST;
- x_io_parms.imrs = MAXINBUF-1;
- x_io_parms.ibad = -1;
- x_io_parms.ircl = -1;
-
- /* IDEL would default to NULL, FF, CR, NL as delimiters.
- * The only delimiters here are CR and NL, for data sensitive
- * records.
- */
- idel_tbl[0] = 0x24;
- x_io_parms.idel = idel_tbl;
-
- zero((char *) &x_io_scrn, sizeof(x_io_scrn));
- x_io_parms.etsp = &x_io_scrn; /* Screen management extension */
- x_io_parms.etsp |= BIT0; /* Turn on the high bit */
- x_io_scrn.esfc &= ~$ESNE; /* Echo input data */
- x_io_scrn.esfc &= ~$ESSE; /* No screen edit */
- x_io_scrn.esfc |= $ESGT; /* Dump ring buffer */
-
- memcpy((char *) &xout_parms,(char *) &x_io_parms,sizeof(x_io_parms));
- xout_parms.isti = $IBIN|$RTDY|$ICRF|$OFOT;
- xout_parms.etsp = 0; /* Screen management extension */
-
- username = getenv("LOGNAME");
-
- /* Zero the console characteristics arrays */
- zero ((char *) charconin, sizeof(charconin));
- zero ((char *) charconout, sizeof(charconout));
- zero ((char *) chartty, sizeof(chartty));
- zero ((char *) charttyin, sizeof(charttyin));
- zero ((char *) charttyout, sizeof(charttyout));
-
- /* Initialize charconin & out,
- * and set up the console for CHAR/BREAK=BMOB
- */
- if (sys_gechr( channel(0), (1<<31)|$CLMAX, charconin))
- { perror("sysinit: gechr 0"); return(-1); }
- if (sys_gechr( channel(1), (1<<31)|$CLMAX, charconout))
- { perror("sysinit: gechr 1"); return(-1); }
- charconin[4] &= ~$CBKM;
- charconin[4] |= $CBBM;
- if (sys_sechr( channel(0), (1<<31)|$CLMAX, charconin))
- { perror("sysinit: sechr stdin "); return(-1); }
- if (sys_sechr( channel(1), (1<<31)|$CLMAX, charconout))
- { perror("sysinit: sechr stdout "); return(-1); }
-
- return(0);
- }
-
- /* S E T T O -- set timeout on the channel to period.
- Save the old characteristics in char***in[].
- */
- /* AOS/VS device timeouts are used sparingly in this implementation of */
- /* Kermit. In most cases, signals are used instead. --ENH */
-
- int setto(chan, period) int chan, period;
- {
- int isconsole = 0;
- int iscon[2]; /* Flags because i/o could be redirected */
-
- /* Setting is done external to here, since they can distinguish the
- console from ttyfd device. Both console channels must be set
- the same.
- */
- if ( (chan == channel(0)) || (chan == channel(1)) ) {
- isconsole = 1; zero((char *) iscon, sizeof(iscon));
- chan = channel(0);
- if (sys_gechr( channel(0), (1<<31)|$CLMAX, charconin))
- if (isatty(0)) {
- iscon[0] = 1;
- perror("setto: gechr 0: ");
- return(-1);
- }
- charcurr = charconin;
- if (sys_gechr( channel(1), (1<<31)|$CLMAX, charconout))
- if (isatty(1)) {
- iscon[1] = 1;
- perror("setto: gechr 1: ");
- return(-1);
- }
- timocon = period;
- }
-
- else {
- if (sys_gechr( chan, (1<<31)|$CLMAX, chartty))
- { perror("setto: gechr tty: "); return(-1); }
- charcurr = chartty;
- timotty = period;
- }
-
- charcurr[1] |= (0100000>>$CTO);
- if (sys_sechr( chan, (1<<31)|$CLMAX, charcurr))
- if ((isconsole == 0) || iscon[0]) {
- perror("setto: sechr: ");
- return(-1);
- }
- if (sys_stom( chan, 1<<31, period))
- if ((isconsole == 0) || iscon[0]) {
- perror("setto: stom: ");
- return(-1);
- }
-
- if (isconsole == 0) return(0);
-
- chan = channel(1);
- charconout[1] |= (0100000>>$CTO);
- if (sys_sechr( chan, (1<<31)|$CLMAX, charconout))
- if (iscon[1]) {
- perror("setto: sechr 1: ");
- return(-1);
- }
- if (sys_stom( chan, 1<<31, period))
- if (iscon[1]) {
- perror("setto: stom 1: ");
- return(-1);
- }
- return(0);
- }
-
-
- /* R E S T O -- reset timeouts to the previous values, and restore char */
-
- int
- resto(chan) int chan;
- {
- int i, chan0, chan1, iscon[2];
-
- if ( (chan==channel(0)) || (chan==channel(1)) ) {
-
- chan0 = channel(0); chan1 = channel(1);
- iscon[0] = isatty(0); iscon[1] = isatty(1);
- charconin[1] &= ~(0100000>>$CTO);
- if (sys_stom( chan0, 1<<31, -1))
- if (iscon[0]) {
- perror("resto: stom 0: ");
- return(-1);
- }
- for (i = 0; i < $CLMAX; i++) if (charconin[i] != 0) {
- if (sys_sechr( chan0, (1<<31)|$CLMAX, charconin))
- if (iscon[0]) {
- perror("resto: sechr 0: ");
- return(-1);
- }
- break;
- }
- charconout[1] &= ~(0100000>>$CTO);
- if (sys_stom( chan1, 1<<31, -1))
- if (iscon[1]) {
- perror("resto: stom 1: ");
- return(-1);
- }
- for (i = 0; i < $CLMAX; i++) if (charconout[i] != 0) {
- if (sys_sechr( chan1, (1<<31)|$CLMAX, charconout))
- if (iscon[1]) {
- perror("resto: sechr 1: ");
- return(-1);
- }
- break;
- }
-
- timocon = 0;
- }
- else {
- chartty[1] &= ~(0100000>>$CTO);
- if (sys_stom( chan, 1<<31, -1))
- { perror("setto: stom tty: "); return(-1); }
- for (i = 0; i < $CLMAX; i++) if (chartty[i] != 0) {
- if (sys_sechr( chan, (1<<31)|$CLMAX, chartty))
- { perror("resto: sechr tty: "); return(-1); }
- break;
- }
- timotty = 0;
- }
-
- return(0);
- }
-
-
- /* S E T F L O W -- Set flow control in the device.
-
- The device is assumed to be an intelligent IAC, where a CHAR/ON/IFC/OFC
- could be done.
-
- */
- int setflow(chan) int chan;
- {
- short termparms[$CLMAX];
-
- if (sys_gechr( chan, (1<<31)|$CLMAX, termparms))
- { perror("setflow: gechr "); return(-1); }
-
- bitset(&termparms[4],$XOFC,1);
- bitset(&termparms[4],$XIFC,1);
-
- if (sys_sechr( chan, (1<<31)|$CLMAX, termparms))
- { perror("setflow: sechr "); return(-1); }
-
- return(0);
- }
-
-
- /* R E S F L O W -- Re-Set flow control in the device.
-
- The device is assumed to be an intelligent IAC, where a CHAR/OFF/IFC/OFC
- could be done.
-
- */
- int resflow(chan) int chan;
- {
- int i;
- short termparms[$CLMAX];
-
- if (sys_gechr( chan, (1<<31)|$CLMAX, termparms))
- { perror("resflow: gechr "); return(-1); }
-
- bitset(&termparms[4],$XOFC,0);
- bitset(&termparms[4],$XIFC,0);
-
- if (sys_sechr( chan, (1<<31)|$CLMAX, termparms))
- { perror("resflow: sechr "); return(-1); }
-
- return(0);
- }
-
-
- /* S E T S P E E D -- Set the baud rate when not possible thru IOCTL.
-
- The device is assumed to be an intelligent IAC, where a CHAR/ON/BAUD=
- could be done.
-
- */
- int setspeed(sp) int sp;
- {
- short termparms[$CLMAX];
-
- /* ttyfd is the Unix file number for the tty device. Setting the
- * characteristics will set it for both ttyfd and ttyfdout, since
- * it is the device itself which is affected, and not just the
- * channel.
- */
- if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, termparms))
- { perror("setspeed: gechr "); return(-1); }
-
- termparms[3] &= ~$BRMSK; /* Zero out the previous setting */
- termparms[3] |= sp;
-
- if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, termparms))
- { perror("setspeed: sechr "); return(-1); }
-
- return(0);
- }
- #endif datageneral
-
- /* S Y S C L E A N U P -- System-dependent cleanup */
-
- int
- syscleanup() {
- return(0);
- }
-
- /* T T O P E N -- Open a tty for exclusive access. */
-
- /*
- Returns:
- 0 on success
- -5 if device is in use
- -4 if access to device is denied
- -3 if access to lock directory denied
- -2 upon timeout waiting for device to open
- -1 on other error
- /*
- If called with lcl < 0, sets value of lcl as follows:
- 0: the terminal named by ttname is the job's controlling terminal.
- 1: the terminal named by ttname is not the job's controlling terminal.
- But watch out: if a line is already open, or if requested line can't
- be opened, then lcl remains (and is returned as) -1.
- */
- int
- ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem,timo; {
-
- /* AOS/VS special stuff */
- FILE *dg_open(); /* Custom file open */
- int retrycnt = 0; /* Retry if Modem disc in progress */
-
- char *ctermid(); /* Wish they all had this! */
- char *x;
- extern char* ttyname();
- char cname[DEVNAMLEN+4];
-
- #define NAMEFD
- #ifdef NAMEFD
- int i, j; char *p;
- debug(F101,"ttopen telnetfd","",telnetfd);
- #endif /* NAMEFD */
-
- debug(F111,"ttopen entry modem",ttname,modem);
- debug(F101," ttyfd","",ttyfd);
- debug(F101," lcl","",*lcl);
-
- if (ttyfd > -1) {
- if (strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are old & new the same? */
- ttclos(ttyfd); /* no? - close old */
- else /* yes? - ignore this call */
- return(0); /* and return */
- }
-
- #ifdef NETCONN
- if (modem < 0) { /* means special code for net type */
- int x;
- ttmdm = modem;
- modem = -modem; /* negative value is net type */
- fdflag = 0; /* stdio not redirected */
- ttyfdout = -1; /* only use ttyfd for nets */
- netconn = 1; /* network connection */
- debug (F111,"ttopen net",ttname,modem);
- #ifdef NAMEFD
- for (p = ttname; isdigit(*p); p++) ; /* check for all digits */
- if (*p == '\0' && telnetfd) {
- ttyfd = atoi(ttname); /* can we test if it's open? */
- ttfdflg = 1; /* we got an open file descriptor */
- debug(F111,"ttopen got open network fd",ttname,ttyfd);
- strncpy(ttnmsv,ttname,DEVNAMLEN); /* remember the "name" */
- x = 1; /* return code is "good" */
- if (telnetfd) {
- ttnet = NET_TCPB;
- ttnproto = NP_TELNET;
- }
- } else {
- #endif /* NAMEFD */ /* hostname or address */
- x = netopen(ttname,lcl,modem); /* (see ckcnet.h) */
- if (x > -1) {
- strncpy(ttnmsv,ttname,DEVNAMLEN);
- } else netconn = 0;
- #ifdef NAMEFD
- }
- #endif NAMEFD
-
- /* ENH - left out ifdef sony_news section */
-
- xlocal = *lcl = 1; /* network connections are local */
- debug(F101,"ttopen net x","",x);
-
- if ((x > -1) && (!x25fd))
- x = tn_ini(); /* initialize telnet protocol */
- return(x);
- } else { /* terminal device */
- #endif /* NETCONN */
-
- #ifdef NAMEFD
- /*
- This code lets you give Kermit an open file descriptor for a serial
- communication device, rather than a device name. Kermit assumes that the
- line is already open, locked, conditioned with the right parameters, etc.
- */
- for (p = ttname; isdigit(*p); p++) ; /* check for all digits */
- if (*p == '\0') {
- ttyfd = atoi(ttname); /* can we test if open? */
- debug(F111,"ttopen got open fd",ttname,ttyfd);
- strncpy(ttnmsv,ttname,DEVNAMLEN); /* remember the "name" */
- xlocal = *lcl = 1; /* assume it's local */
- netconn = 0; /* assume not network */
- tvtflg = 0; /* initialize modes? */
- ttmdm = modem; /* remember modem type */
- fdflag = 0; /* stdio not redirected */
- ttfdflg = 1; /* flag we were opened */
- /* this way */
- /* ENH - left out ifdef sony_news */
-
- return(0); /* return success */
- }
- #endif /* NAMEFD */
- #ifdef NETCONN
- }
- #endif /* NETCONN */
-
- /* Here we have to open a serial device of the given name */
-
- tvtflg = 0; /* flag for use by ttvt() */
- /* 0 means ttvt() not called yet */
- fdflag = (!isatty(0) || !isatty(1));/* flag for stdio redirected */
- debug(F101,"ttopen fdflag","",fdflag);
- ttmdm = modem; /* Make this available to other fns */
- xlocal = *lcl; /* Make this available to other fns */
-
- /* Code for handling bidirectional tty lines goes here.
- /* Use specified method for turning off logins and suppressing getty. */
-
- #ifdef ACUCNTRL
- /* Should put call to priv_on() here, but that would be very risky! */
- acucntrl("disable",ttname); /* acucntrl() program. */
- /* and priv_off() here... */
- #else
- #ifdef ATT7300
- if ((attmodem & DOGETY) == 0) /* offgetty() program. */
- attmodem |= offgetty(ttname); /* Remember response. */
- #endif /* ATT7300 */
- #endif /* ACUCNTRL */
-
- #ifdef datageneral
- /* A custom open is done for the device, but a FILE handle is also needed
- * for doing other special operations on the device. See sysinit() for
- * the initialization of the x_io_parms and xout_parms structures.
- *
- * First open up the output channel ($OFOT)
- */
- idel_tbl[0] = 0x4; /* CR only */
- xout_parms.idel = idel_tbl;
- xout_parms.ifnp = ttname;
-
- /*
- ttotmo = 0;
- saval = signal(SIGALRM,timerh);
- if (timo > 0) {
- alarm(timo);
- if (setjmp(sjbuf)) {
- } else {
- */ /* Ignore timeout for now - let it take as long as it wants */
- retry:
- if ((ttfileout =
- dg_open(ttname, xout_parms.isti, xout_parms.isto,
- xout_parms.imrs,xout_parms.ires,xout_parms.idel))
- == NULL) {
- /* If a modem disconnect, or one in progress, wait and retry. */
- if ((lasterror() == ERDCT) || (lasterror() == ERCDS))
- if (retrycnt == 0) {
- retrycnt = 1;
- sleep(2);
- goto retry;
- }
- ttyfdout = -1;
- perror("ttopen: output_line: dg_open");
- if ((lasterror() == EREO1) || (lasterror() == EREO2)) /* in use */
- return(-5); /* EOF */
- else if (lasterror() == ERFAD)
- return(-4); /* access denied */
- else /* some other error */
- return(-1);
- }
- /* Successfull opens fall through here! */
-
- ttyfdout = fileno(ttfileout); /* Note that ttyfdout is */
- xout_parms.ich = channel(ttyfdout); /* only used for asynch */
-
- /* Next, open up the input channel ($OFIN) */
-
- x_io_parms.ifnp = ttname;
- /* IDEL would default to NULL, FF, CR, NL as delimiters.
- * The only delimiters here are CR and NL, for data sensitive
- * records.
- */
- idel_tbl[0] = 0x24;
- x_io_parms.idel = idel_tbl;
-
- if ((ttfile =
- dg_open(ttname, x_io_parms.isti, x_io_parms.isto,
- x_io_parms.imrs,x_io_parms.ires,x_io_parms.idel,
- (P_SCREEN *) x_io_parms.etsp))
- == NULL) {
- ttyfd = -1;
- perror("ttopen: input_line: dg_open");
- if ((lasterror() == EREO1) || (lasterror() == EREO2)) /* in use */
- return(-5); /* EOF */
- else if (lasterror() == ERFAD)
- return(-4); /* access denied */
- else /* some other error */
- return(-1);
- }
- else {
- ttyfd = fileno(ttfile);
- x_io_parms.ich = channel(ttyfd);
- }
-
- #endif
-
- /* Make sure it's a real tty. */
- if (!isatty(ttyfd)) {
- fprintf(stderr,"%s is not a tty!\n",ttname);
- debug(F110,"ttopen not a tty",ttname,0);
- close(ttyfd);
- ttyfd = -1;
- return(-1);
- }
-
- strncpy(ttnmsv,ttname,DEVNAMLEN); /* Open, keep copy of name locally. */
-
- /* Caller wants us to figure out if line is controlling tty */
-
- debug(F111,"ttopen ok",ttname,*lcl);
- if (*lcl == -1) {
- if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
- debug(F110," Same as CTTNAM",ttname,0);
- xlocal = 0;
- } else if (isatty(0)) { /* Else, if stdin not redirected */
- x = ttyname(0); /* then compare its device name */
- strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
- debug(F110," ttyname(0)",x,0);
- x = ttyname(ttyfd); /* ...with real name of ttname. */
- xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
- debug(F111," ttyname",x,xlocal);
- } /* Else, if stdin redirected... */
- }
-
- /* Now check if line is locked -- if so fail, else lock for ourselves */
-
- lkf = 0; /* Check lock */
- if (xlocal > 0) {
- if (ttlock(ttname) < 0) {
- fprintf(stderr,"Exclusive access to %s denied\n",ttname);
- close(ttyfd); ttyfd = -1;
- debug(F110," Access denied by lock",ttname,0);
-
- return(-3);
- } else lkf = 1;
- }
-
- /* Got the line, now set the desired value for local. */
-
- if (*lcl != 0) *lcl = xlocal;
-
- /* Request exclusive access on systems that allow it. */
-
- #ifdef TIOCEXCL
- if (ioctl(ttyfd,TIOCEXCL, NULL) < 0)
- fprintf(stderr,"Warning, problem getting exclusive access\n");
- #endif
-
- /* Get tty device settings */
-
- ioctl(ttyfd,TCGETA,&ttold); /* Same deal for Sys III, Sys V */
- ioctl(ttyfd,TCGETA,&ttraw);
- ioctl(ttyfd,TCGETA,&tttvt);
-
- debug(F101,"ttopen, ttyfd","",ttyfd);
-
- debug(F101,"ttopen, ttyfdout","",ttyfdout);
- /* For DG, also get the tty extended device characteristics. */
- sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttold);
- sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw);
- sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttvt);
-
- debug(F101," lcl","",*lcl);
- debug(F111," lock file",flfnam,lkf);
- return(0);
- }
-
- /* T T C L O S -- Close the TTY, releasing any lock. */
- int
- ttclos(foo) int foo; {
- int x = 0;
-
- debug(F101,"ttclos ttyfd","",ttyfd);
- if (ttyfd < 0) return(0); /* Wasn't open. */
- if (ttfdflg) return(0); /* If we got ttyfd from another */
- /* process, don't close it. */
- tvtflg = 0;
-
- #ifdef NETCONN
- if (netconn) { /* Network connection. */
- debug(F100,"ttclos closing net","",0);
- netclos(); /* Close it. */
- netconn = 0;
- return(0);
- }
- #endif /* NETCONN */
-
- if (xlocal) {
- debug(F100,"ttclos skipping ttunlck for AOS/VS","",0);
- debug(F100,"ttclos about to call tthang()","",0);
- }
- if (ttyfd > 0) {
- /* & timer stuff & moved closes in */
- saval = signal(SIGALRM,timerh); /* enable timer */
- alarm(5); /* allow 5 seconds for completion */
- if (setjmp(sjbuf)) { /* timer went off */
- x = -1; /* set return value */
- } else { /* what we're really trying to do */
- if (xlocal) {
- if (tthang()) /* Hang up first, then... */
- fprintf(stderr,"Warning, problem hanging up the phone\n");
- ttres(); /* reset device modes. */
- }
- #ifdef TIOCEXCL
- #ifdef TIOCNXCL
- if (ioctl(ttyfd, TIOCNXCL, NULL) < 0)
- fprintf(stderr,"Problem relinquishing exclusive access\n");
- #endif
- #endif
-
- debug(F101,"ttclos, ttyfd","",ttyfd);
- debug(F101,"ttclos, ttyfdout","",ttyfdout);
- fclose(ttfile); /* Close it. */
-
- /* Close the output tty device */
- fclose(ttfileout); /* Close it. */
- x = 1; /* good return */
- }
- ttimoff(); /* turn off timer */
- if (x < 0) {
- fprintf(stderr,"?Timed out closing device: %s\n",ttnmsv);
- debug(F100,"ttclos timed out","",0);
- }
- }
- ttyfd = -1; /* Mark it as closed. */
- ttyfdout = -1; /* Mark it as closed. */
-
- debug(F100,"ttclos done","",0);
- return(0);
- }
-
- /* T T H A N G -- Hangup phone line */
-
- tthang() {
- unsigned short ttc_save;
- int x;
-
- if (ttyfd < 0) return(0); /* Not open. */
- if (xlocal < 1) return(0);
-
- #ifdef NETCONN
- if (netconn) { /* Network connection. */
- return ((netclos() < 0) ? -1 : 1); /* Close it */
- }
- #endif /* NETCONN */
-
- ttc_save = ttraw.c_cflag;
- ttraw.c_cflag &= ~CBAUD; /* swa: set baud rate to 0 to hangup */
- if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */
- msleep(100); /* let things settle */
- ttraw.c_cflag = ttc_save;
- debug(F100, "tthang disconnecting line","",0);
- if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw))
- { perror("tthang: sechr "); return(-1); }
- if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */
- return (0);
- }
-
-
- /* T T R E S -- Restore terminal to "normal" mode. */
-
- ttres() { /* Restore the tty to normal. */
- int x;
-
- if (ttyfd < 0) return(-1); /* Not open. */
-
- if (ttfdflg) return(0); /* Don't mess with terminal modes if */
- /* we got ttyfd from another process */
- #ifdef NETCONN
- if (netconn) return (0); /* Network connection, do nothing */
- #endif /* NETCONN */
-
- x = (ioctl(ttyfd,TCSETAW,&ttold) < 0); /* restore termio stuff */
-
- /* Un-set all the timeouts */
- if (timotty) {
- resto(channel(ttyfd));
- resto(channel(ttyfdout));
- }
- if (sys_sechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttold))
- { perror("ttres: sechr "); return(-1); }
-
- return(0);
- }
-
- /* Exclusive uucp file locking control */
- /*
- by H. Fischer, creative non-Bell coding !
- copyright rights for lock modules assigned to Columbia University
- */
-
- /* The AOS/VS implementation does not use uucp locks. --ENH */
-
- static char *
- xxlast(s,c) char *s; char c; { /* Equivalent to strrchr() */
- int i;
- for (i = strlen(s); i > 0; i--)
- if ( s[i-1] == c ) return( s + (i - 1) );
- return(NULL);
- }
- static
- look4lk(ttname) char *ttname; {
- extern char *strcat(), *strcpy();
- char *device, *devname;
- char lockfil[50]; /* Max length for lock file name */
- char *lockdir = "/usr/spool/uucp";
-
- device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
-
- strcat( strcpy( lockfil, "LCK.." ), device );
-
- if (access( lockdir, 04 ) < 0) { /* read access denied on lock dir */
- fprintf(stderr,"Warning, read access to lock directory denied\n");
- return( 1 ); /* cannot check or set lock file */
- }
-
- strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil);
- debug(F110,"look4lk",flfnam,0);
-
- if ( ! access( flfnam, 00 ) ) { /* print out lock file entry */
- char lckcmd[40] ;
- strcat( strcpy(lckcmd, "ls -l ") , flfnam);
- system(lckcmd);
- if (access(flfnam,02) == 0)
- printf("(You may type \"! rm %s\" to remove this file)\n",flfnam);
- return( -1 );
- }
- if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */
- fprintf(stderr,"Warning, write access to lock directory denied\n");
- return( 1 );
- }
-
- return( 0 ); /* okay to go ahead and lock */
- }
-
- /* T T L O C K */
-
-
- static
- ttlock(ttyfd) char *ttyfd; { /* lock uucp if possible */
-
- #ifdef datageneral
- /* The Data General locks a device when that device is opened. So
- * return that the device is already locked.
- * Besides, because of internal multi-tasking, locking the device by
- * the ?ASSIGN call or an $IEXO flag would cause problem for the task
- * id that did not open the device first.
- */
- #else datageneral
- int lck_fil, l4l;
- int pid_buf = getpid(); /* pid to save in lock file */
-
- haslock = 0; /* not locked yet */
- l4l = look4lk(ttyfd);
- if (l4l < 0) return (-1); /* already locked */
- if (l4l == 1) return (0); /* can't read/write lock directory */
- lck_fil = creat(flfnam, 0444); /* create lock file ... */
- if (lck_fil < 0) return (-1); /* create of lockfile failed */
- /* creat leaves file handle open for writing -- hf */
- write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */
- close (lck_fil);
- #endif datageneral
- haslock = 1; /* now is locked */
- return(0);
- }
-
- /* T T U N L O C K */
-
- static
- ttunlck() { /* kill uucp lock if possible */
- #ifdef datageneral
- /* The DG automatically unlocks the device when it is closed, or when
- * the process is terminated for any reason. Unlocking is not needed.
- * Also, see the note for ttlock().
- */
- return(0);
- #else
- if (haslock) return( unlink( flfnam ) );
- #endif
-
- }
-
- /* T T P K T -- Condition the communication line for packets. */
- /* or for modem dialing */
-
- #define DIALING 4 /* flags (via flow) for modem handling */
- #define CONNECT 5
-
- /* If called with speed > -1, also set the speed. */
-
- /* Returns 0 on success, -1 on failure. */
-
- ttpkt(speed,xflow,parity) long speed; int xflow, parity; {
- int s2;
- int s = -1;
- int x;
- extern int flow; /* REAL flow-control setting */
-
- if (ttyfd < 0) return(-1); /* Not open. */
-
- debug(F101,"ttpkt parity","",parity);
- debug(F101,"ttpkt xflow","",xflow);
- debug(F101,"ttpkt speed","",(int) speed);
-
- ttprty = parity; /* Let other tt functions see these. */
- ttpflg = 0; /* Parity not sensed yet */
- ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
- ttspeed = speed;
-
- #ifdef NETCONN /* Nothing to do for telnet */
- if (netconn) return (0);
- #endif /* NETCONN */
-
- if (ttfdflg && !isatty(ttyfd)) return(0);
-
- if (xflow != FLO_DIAL && xflow != FLO_DIAX)
- ttflow = xflow; /* Now make this available too. */
-
- if (xlocal) {
- s2 = (int) (speed / 10L); /* convert bps to cps */
- s = ttsspd(s2); /* get associated speed */
- if (s < 0)
- return(-1);
- /* carrctl() call here in UNIX code */
- }
-
- #ifdef UXIII
- if (flow == FLO_XONX) ttraw.c_iflag |= (IXON|IXOFF);
- else if (flow == FLO_NONE) ttraw.c_iflag &= ~(IXON|IXOFF);
- else if (flow == FLO_KEEP) {
- ttraw.c_iflag &= ~(IXON|IXOFF);
- ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF));
- } else if (flow == FLO_RTSC) {
- /* RTS/CTS Flow control... */
- #ifdef RTSXOFF
- /* This is the preferred way, according to SVID R4 */
- if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
- rctsx.x_hflag |= RTSXOFF | CTSXON;
- ioctl(ttyfd,TCSETX,&rctsx); /* Ignore errors for now. */
- }
- #else
- #ifdef CRTSCTS
- /* Found this one in <termios.h> */
- ttraw.c_iflag |= CRTSCTS;
- #endif /* CRTSCRS */
- #endif /* RTSXOFF */
- }
- if (flow == FLO_DTRC) {
- /* DTR/CD Flow control... */
- #ifdef DTRXOFF
- /* This is straight out of SVID R3 */
- if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
- rctsx.x_hflag |= DTRXOFF | CDXON;
- ioctl(ttyfd,TCSETX,&rctsx); /* Ignore errors. */
- }
- #endif /* DTRXOFF */
- }
- if (flow == DIALING) ttraw.c_cflag |= CLOCAL|HUPCL;
- if (flow == CONNECT) ttraw.c_cflag &= ~CLOCAL;
-
- ttraw.c_lflag &= ~(ICANON|ECHO);
- ttraw.c_lflag &= ~ISIG;
- ttraw.c_lflag |= NOFLSH; /* Don't flush */
- ttraw.c_iflag |= (BRKINT|IGNPAR);
- ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
- ttraw.c_oflag &= ~OPOST;
- #ifdef datageneral
- ttraw.c_lflag &= ~CSETPM; /* No DG page mode */
- #endif
- ttraw.c_cc[4] = 1;
- ttraw.c_cflag &= ~(CSIZE|PARENB);
- ttraw.c_cflag |= (CS8|CREAD);
- ttraw.c_cc[5] = 0;
-
- #ifdef VINTR /* Turn off interrupt character */
- if (xlocal == 0) /* so ^C^C can break us out of */
- ttraw.c_cc[VINTR] = 0; /* packet mode. */
- #endif /* VINTR */
-
- if (s > -1) {
- ttraw.c_cflag &= ~CBAUD;
- ttraw.c_cflag |= s; /* set speed */
- }
-
- if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */
- #ifdef datageneral
- if (flow == FLO_XONX) {
- setflow(channel(ttyfdout));
- setflow(channel(ttyfd));
- }
- if (flow == FLO_NONE) {
- resflow(channel(ttyfdout));
- resflow(channel(ttyfd));
- }
- /* if flow is FLO_KEEP, don't do anything */
- if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttraw))
- { perror("ttpkt: gechr: "); return(-1); }
- #endif
-
- if (flow == DIALING) {
- #ifdef datageneral
- #ifndef aosvs
- if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0)) < 0 )
- return(-1);
- #endif
- #else
- if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
- return(-1);
- close( open(ttnmsv,2) ); /* magic to force mode change!!! */
- #endif
- }
-
- #endif
-
- ttflui(); /* Flush any pending input */
- tvtflg = 0;
- return(0);
- }
-
- /* T T V T -- Condition communication line for use as virtual terminal */
-
- ttvt(speed,flow) int speed, flow; {
- int s, s2;
-
- debug(F101,"ttvt ttyfd","",ttyfd);
- debug(F101,"ttvt tvtflg","",tvtflg);
- debug(F101,"ttvt speed","",speed);
-
- if (ttyfd < 0) return(-1); /* Not open. */
-
- #ifdef NETCONN
- if (netconn) {
- tvtflg = 1; /* Network connections */
- return(0); /* require no special setup */
- }
- #endif /* NETCONN */
-
- if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr)
- return(0); /* Already been called. */
-
- if (ttfdflg && !isatty(ttyfd)) return(0);
-
- if (xlocal) {
- s2 = (int) (speed / 10L); /* convert bps to cps */
- s = ttsspd(s2); /* Check the speed */
- /* ENH - UNIX has call to carrctl here */
- }
- if (flow == FLO_XONX) tttvt.c_iflag |= (IXON|IXOFF);
- else if (flow == FLO_KEEP) {
- tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
- tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
- }else if (flow == FLO_NONE) tttvt.c_iflag &= ~(IXON|IXOFF);
-
- if (flow == DIALING) tttvt.c_cflag |= CLOCAL|HUPCL;
- if (flow == CONNECT) tttvt.c_cflag &= ~CLOCAL;
-
- tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
- tttvt.c_iflag |= (IGNBRK|IGNPAR);
- tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
- tttvt.c_oflag &= ~OPOST;
- tttvt.c_cflag &= ~(CSIZE|PARENB);
- tttvt.c_cflag |= (CS8|CREAD);
- tttvt.c_cc[4] = 1;
- tttvt.c_cc[5] = 0;
-
- if (s > -1) {
- tttvt.c_cflag &= ~CBAUD;
- tttvt.c_cflag |= s; /* set speed */
- }
-
- if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */
-
- #ifdef datageneral
- if (flow == FLO_XONX) {
- setflow(channel(ttyfdout));
- setflow(channel(ttyfd));
- }
- if (flow == FLO_NONE) {
- resflow(channel(ttyfdout));
- resflow(channel(ttyfd));
- }
- if (sys_gechr( channel(ttyfd), (1<<31)|$CLMAX, ch_ttvt))
- { perror("ttvt: gechr: "); return(-1); }
- #endif
-
- if (flow == DIALING) {
- #ifdef datageneral
- #ifndef aosvs
- if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0)) < 0 )
- return(-1);
- #endif
- #else
- if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
- return(-1);
- close( open(ttnmsv,2) ); /* magic to force mode change!!! */
- #endif
- }
-
- ttspeed = speed; /* Done, remember how we were */
- ttflow = flow; /* called, so we can decide how to */
- tvtflg = 1; /* respond next time. */
-
- debug(F101,"ttvt done","",tvtflg);
- return(0);
- }
-
- /* T T S S P D -- Return the internal baud rate code for 'speed'. */
-
- ttsspd(cps) {
- int s,s2,spdok;
-
- debug(F101,"ttsspd","",cps);
-
- #ifdef NETCONN
- if (netconn) return (0);
- #endif /* NETCONN */
-
- if (cps < 0) return(-1);
- spdok = 1; /* Assume arg ok */
- switch (cps) {
- case 0: s = B0; break; /* Just the common ones. */
- case 11: s = B110; break; /* The others from ttydev.h */
- case 15: s = B150; break; /* could also be included if */
- case 30: s = B300; break; /* necessary... */
- case 60: s = B600; break;
- case 120: s = B1200; break;
- case 180: s = B1800; break;
-
- case 240: s = B2400; break;
- case 480: s = B4800; break;
- case 960: s = B9600; break;
- #ifdef datageneral
- /* ioctl() allows other speeds */
- case 5: s = B50; break;
- case 7: s = B75; break;
- case 13: s = B134; break;
- case 360: s = B3600; break;
- case 720: s = B7200; break;
- case 1920: s = B19000; break;
-
- /* Some speeds are supported by the hardware thru PMGR.
- We don't bother about 45.5 but it could be added.
- */
- case 38400: if (setspeed($CR38K)) spdok = 0; s = 0; break;
- #endif
- default:
- spdok = 0;
- fprintf(stderr,"Unsupported line speed - %d\n",cps * 10);
- fprintf(stderr,"Current speed not changed\n");
- break;
- }
- if (spdok)
- return(s);
- else
- return(-1);
- }
-
- /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
- *
- * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
- * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
- * 2 = Auto: For "modem direct": The same as "Off".
- * For real modem types: Heed carrier during connect, but ignore
- * it anytime else. Compatible with pre-5A C-Kermit versions.
- *
- * As you can see, this setting does not affect dialing, which always ignores
- * carrier (unless there is some special exception for some modem type). It
- * does affect ttopen() if it is set before ttopen() is used. This setting
- * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
- * (or should be) always called before any communications is tried, which
- * means that, practically speaking, the effect is immediate.
- *
- * Of course, nothing of this applies to remote mode (xlocal = 0).
- *
- * Someone has yet to uncover how to manipulate the carrier in the BSD
- * environment (or any non-termio using environment). Until that time, this
- * will simply be a no-op for BSD.
- *
- * Note that in previous versions, the carrier was most often left unchanged
- * in ttpkt()/ttvt() unless they were called with DIALING or CONNECT. This
- * has changed. Now it is controlled by ttcarr in conjunction with these
- * modes.
- */
- int
- ttscarr(carrier) int carrier; {
- ttcarr = carrier;
- debug(F101, "ttscarr","",ttcarr);
- return(ttcarr);
- }
-
- int
- ttgmdm() { /* Read modem signals */
- return(-3); /* ENH - return value of -3 means */
- } /* not implemented, which it's not */
- /* because this can't (easily) be */
- /* done in AOS/VS */
-
- int
- ttwmdm(mdmsig,timo) int mdmsig,timo; { /* wait timo seconds for specified */
- return(-3); /* modem signals to appear */
- }
-
-
- long
- ttgspd() { /* Get line speed */
- P_CHAR_EX cp; /* characteristics packet */
- int ac0,ac1,ac2,error;
- static int baud_rate[] = {
- 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,
- 7200,9600,19200},
- baud_rate_x[] = {45,38400};
-
- #ifdef NETCONN
- if (netconn) return (-1);
- #endif /* NETCONN */
-
- if (ttyfd < 0)
- return (-1);
- else {
- ac0 = channel(ttyfd);
- ac1 = $CLMAX | BIT0;
- ac2 = (P_CHAR_EX *) &cp;
- error = sys($GECHR,&ac0,&ac1,&ac2);
- if (error)
- return(-1);
-
- if (cp.char_br0bit == 0)
- return(baud_rate[cp.char_br_1_4]);
- else
- return(baud_rate_x[cp.char_br_1_4]);
- }
- }
-
- int
- psuspend() { /* ENH - not possible in VS */
- return(-1);
- }
-
- /* Interrupt Functions */
-
- /* Set up terminal interrupts on console terminal */
-
- #ifdef UXIII
- esctrp() { /* trap console escapes (^\) */
-
- conesc = 1;
- signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
- }
- #endif
-
- /* C O N I N T -- Console Interrupt setter */
- VOID
- conint(f,s) SIGTYP (*f)(), (*s)(); { /* Set an interrupt trap. */
-
- if (!isatty(0)) { /* only for real ttys */
- debug(F101,"conint not a tty","",isatty(0));
- return;
- }
- if (backgrd) { /* must ignore signals in bkgrd */
- debug(F101,"conint backgrd ignoring signals","",backgrd);
- return;
- }
- else debug(F101,"conint foreground catching signals","",0);
- /*
- Except for special cases below, ignore keyboard quit signal.
- ^\ too easily confused with connect escape, and besides, we don't want
- to leave lock files around. (Frank Prindle)
- */
- #ifdef datageneral
- /* Set up the asynchronous task to read the console.
- * But, I don't want them set up all the time, so I will kludge up the
- * call in chkint() (ckuus3.c) to see if this asynch task is running:
- * conint_mt()
- */
- #endif
- signal(SIGQUIT,SIG_IGN);
-
- #ifdef UXIII
- signal(SIGQUIT,esctrp); /* console escape in pkt modes */
- if (conesc) { /* clear out pending escapes */
- conesc = 0;
- }
- #endif
-
- if (conif) return; /* Nothing to do if already on. */
-
- /* check if invoked in background -- if so signals set to be ignored */
-
- if (signal(SIGINT,SIG_IGN) == SIG_IGN) {
- backgrd = 1; /* means running in background */
- #ifdef UXIII
- signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */
- #endif
- return;
- }
- signal(SIGINT,f); /* Function to trap to on interrupt. */
- signal(SIGHUP,f); /* Or hangup, so lock file cleared. */
- conif = 1; /* Flag console interrupts on. */
- }
-
-
- /* C O N N O I -- Reset console terminal interrupts */
-
- connoi() { /* Console-no-interrupts */
-
- if (!isatty(0)) return(0); /* only for real ttys */
- if (backgrd) return; /* Ignore signals in background */
-
- #ifdef datageneral
- /* Terminate the asynchronous task that reads the console for
- * interrupt characters.
- * But, I don't want to kill this task all the time, so I will kludge
- * up the call in input() (ckcfn2.c) to kill the asynch task if it
- * is running: connoi_mt()
- */
- #endif
- signal(SIGINT,SIG_DFL);
- signal(SIGHUP,SIG_DFL);
- signal(SIGQUIT,SIG_DFL);
- conif = 0; /* Flag interrupt trapping off */
- }
-
- #ifdef datageneral
- /* C O N I N T _ M T -- Asynch read console task */
-
- void conint_mt() {
- int count = 0;
-
- /* Any input waiting? */
- con_reads_mt = 1; /* Flag that task is active */
- conint_avl = 0; /* Flag that interrupt gotten */
- while (con_reads_mt)
- if ((conint_ch = coninc(2)) > 0) { /* If character at keyboard */
- conint_avl = 1; /* we set the flag */
- while ((conint_avl) && (++count <= 5))
- sleep(1); /* & wait for char to be processed */
- }
- count = 0; /* initialize counter */
- conint_avl = 0;
- }
-
-
- /* C O N N O I _ M T -- Kill asynch read console task */
-
- connoi_mt() {
- conint_avl = 0;
- if (con_reads_mt) {
- con_reads_mt = 0;
- midkill(CONINT_TSK);
- }
- }
-
-
- /* C O N S T A _ M T -- Start the console asynch read task */
-
- consta_mt() {
- if ((con_reads_mt == 0) /* Not already running */
- && (mtask(conint_mt, CONINT_STACK, CONINT_TSK, CONINT_PRI) != 0))
- perror("consta_mt: Can't initiate task:");
- }
- #endif datageneral
-
- /* Private buffer for myread() and its companions. Not for use by anything
- * else. ttflui() is allowed to reset them to initial values. ttchk() is
- * allowed to read my_count.
- *
- * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
- *
- * A global parity mask variable could be useful too. We could use it to
- * let myread() strip the parity on its own, instead of stripping sign
- * bits as it does now.
- */
-
- #define MYBUFLEN 256
- #define PEEKTYPE long
- static CHAR mybuf[MYBUFLEN]; /* Buffer, including push back */
- static int my_count = 0; /* Number of chars still in mybuf */
- static int my_item = -1; /* Last index read from mybuf[] */
-
- /* myread() -- Efficient read of one character from communications line.
- *
- * Uses a private buffer to minimize the number of expensive read() system
- * calls. Essentially performs the equivalent of read() of 1 character, which
- * is then returned. By reading all available input from the system buffers
- * to the private buffer in one chunk, and then working from this buffer, the
- * number of system calls is reduced in any case where more than one character
- * arrives during the processing of the previous chunk, for instance high
- * baud rates or network type connections where input arrives in packets.
- * If the time needed for a read() system call approaches the time for more
- * than one character to arrive, then this mechanism automatically compensates
- * for that by performing bigger read()s less frequently. If the system load
- * is high, the same mechanism compensates for that too.
- *
- * myread() is a macro that returns the next character from the buffer. If the
- * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
- * returns.
- *
- * This should be efficient enough for any one-character-at-a-time loops.
- * For even better efficiency you might use memcpy()/bcopy() or such between
- * buffers (since they are often better optimized for copying), but it may not
- * be worth it if you have to take an extra pass over the buffer to strip
- * parity and check for CTRL-C anyway.
- *
- * Note that if you have been using myread() from another program module, you
- * may have some trouble accessing this macro version and the private variables
- * it uses. In that case, just add a function in this module, that invokes the
- * macro.
- */
-
- #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
-
-
- /* not used right now */
- /*
- myunrd(ch) CHAR ch; {
- ungotn = ch;
- }
- */
-
- /* mygetbuf() -- Fill buffer for myread() and return first character.
- *
- * This function is what myread() uses when it can't get the next character
- * directly from its buffer. First, it calls a system dependent myfillbuf()
- * to read at least one new character into the buffer, and then it returns
- * the first character just as myread() would have done. This function also
- * is responsible for all error conditions that myread() can indicate.
- *
- * Returns: When OK => a positive character, 0 or greater.
- * When EOF => -2.
- * When error => -3, error code in errno.
- *
- * Older myread()s additionally returned -1 to indicate that there was nothing
- * to read, upon which the caller would call myread() again until it got
- * something. The new myread()/mygetbuf() always gets something. If it
- * doesn't, then make it do so! Any program that actually depends on the old
- * behaviour will break.
- *
- * The older version also used to return -2 both for EOF and other errors,
- * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
- * other errors now return different results, although Kermit currently never
- * checks to see which it was. It just disconnects in both cases.
- *
- * Kermit lets the user use the quit key to perform some special commands
- * during file transfer. This causes read(), and thus also mygetbuf(), to
- * finish without reading anything and return the EINTR error. This should
- * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
- * but if there is nothing to read, this could delay Kermit's reaction to
- * the command, and make Kermit appear unresponsive.
- *
- * The debug() call should be removed for optimum performance.
- */
- int
- mygetbuf() {
- my_count = myfillbuf();
- /* debug(F101, "myfillbuf read", "", my_count); */
- if (my_count <= 0)
- return(my_count < 0 ? -3 : -2);
- --my_count;
- return(255 & (int)mybuf[my_item = 0]);
- }
-
- /* myfillbuf():
- * System-dependent read() into mybuf[], as many characters as possible.
- *
- * Returns: OK => number of characters read, always more than zero.
- * EOF => 0
- * Error => -1, error code in errno.
- *
- * If there is input available in the system's buffers, all of it should be
- * read into mybuf[] and the function return immediately. If no input is
- * available, it should wait for a character to arrive, and return with that
- * one in mybuf[] as soon as possible. It may wait somewhat past the first
- * character, but be aware that any such delay lengthens the packet turnaround
- * time during kermit file transfers. Should never return with zero characters
- * unless EOF or irrecoverable read error.
- *
- * Correct functioning depends on the correct tty parameters being used.
- * Better control of current parameters is required than may have been the
- * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
- * no longer be sometimes off and sometimes on like it used to, unless a
- * special myfillbuf() is written to handle that. Otherwise the ordinary
- * myfillbuf()s may think they have come to EOF.
- *
- * If your system has a facility to directly perform the functioning of
- * myfillbuf(), then use it. If the system can tell you how many characters
- * are available in its buffers, then read that amount (but not less than 1).
- * If the system can return a special indication when you try to read without
- * anything to read, while allowing you to read all there is when there is
- * something, you may loop until there is something to read, but probably that
- * is not good for the system load.
- */
- int
- myfillbuf() {
- int n;
- int retry_count = 5; /* max # of retries */
-
- #ifdef NETCONN
- if (netconn) {
- n = read(ttyfd, mybuf, sizeof(mybuf));
- if (n <= 0)
- debug(F101,"myfillbuf() got error reading from network, ","",n);
- return(n);
- } else { /* console read */
- #endif /* NETCONN */
- while (1) {
- n = dgncinb(ttyfd, mybuf, sizeof(mybuf));
- if (n > 0) {
- return(n);
- }
- if ((n == -EROVR) || (n == -1) || (n == -2) || (n == 0)) {
- if (n == -EROVR)
- debug(F101,"myfillbuf() got data overrun ind., ","",-n);
- else if (n == -1)
- debug(F101,"myfillbuf() got EOF ind., ","",n);
- else if (n == -2)
- debug(F101,"myfillbuf() got device timeout ind., ","",n);
- else
- debug(F101,"myfillbuf() got zero characters, ","",n);
- if (--retry_count > 0) {
- debug(F101,"myfillbuf() tries remaining, ","",retry_count);
- sleep(1); /* keep trying on data over- */
- continue; /* run, EOF (-1), timeout (-2) & 0 */
- }
- } else if (n < -2) /* VS errors complimented */
- debug(F101,"myfillbuf() got AOS/VS error ","",-n);
- if (n == -1) /* EOF is -1, but caller */
- n = 0; /* wants it to be zero */
- else n = -1; /* all others -1 */
- return(n);
- }
- #ifdef NETCONN
- }
- #endif /* NETCONN */
- }
-
- /* T T C H K -- Tell how many characters are waiting in tty input buffer */
-
- ttchk() {
- int x;
- PEEKTYPE n = 0;
-
- #ifdef COMMENT
- /*
- This was REALLY slowing TELNET connections down! Just do the regular
- ttyfd-based stuff here. Let the VMS version call nettchk if it has to...
- FIONREAD definitely works for TELNET, at least on the NeXT and SUNOS.
- */
- #ifdef NETCONN
- if (netconn) return (nettchk());
- #endif /* NETCONN */
- #endif /* COMMENT */
-
- if (my_count > 0) /* Sys III, Sys V, Apollo Aegis, etc */
- n += my_count;
- debug(F101,"ttchk chars available, ","",n);
- return(n);
- }
-
- /* T T F L U I -- Flush tty input buffer */
-
- ttflui() {
- int ffd;
-
- #ifndef UXIII
- long n;
- #endif
-
- my_count = 0; /* Initialize myread() stuff */
- my_item = -1;
-
- #ifdef NETCONN
- if (netconn) return(netflui());
- #endif /* NETCONN */
-
- ffd = xlocal ? ttyfd : 0; /* If not local, use stdin */
- debug(F101,"ttflui xlocal","",xlocal);
- debug(F101,"ttflui ttyfd","",ttyfd);
- debug(F101,"ttflui ffd","",ffd);
-
- if (ffd < 0) return(-1); /* Not open. */
-
-
- #ifdef UXIII
- #ifdef datageneral
- /* Since $ESGT is turned on in the sys_read packets, there is never a need
- * to flush the input buffer -- the system automatically does it each time
- * a read is issued.
- */
- #endif
- #endif
-
- return(0);
- }
-
- int
- ttfluo() { /* Flush output buffer - dummy */
- return(0); /* POSIX is only implementation */
- } /* that needs this */
-
-
- /* T T X I N -- Get n characters from tty input buffer */
-
- /* Returns number of characters actually gotten, or -1 on failure */
-
- /* Intended for use only when it is known that n characters are actually */
- /* Available in the input buffer. */
-
- ttxin(n,buf) int n; CHAR *buf; {
- int x;
- int c;
-
- ttpmsk = (ttprty) ? 0177: 0377; /* parity stripping mask */
- debug(F101,"ttxin: n","",n);
-
- for( x = 0; (x > -1) && (x < n) && (c = myread()) >= 0; )
- buf[x++] = c & ttpmsk;
-
- debug(F101," x","",x);
- for (c = 0; c < n; c++)
- buf[c] &= ttpmsk;
- if (x > 0) buf[x] = '\0';
- else if (x < 0) x = -1;
- return(x);
- }
-
- #define TTOLMAXT 5
-
- /* T T O L -- Similar to "ttinl", but for writing. */
-
- ttol(s,n) int n; char *s; {
- int x,len,tries,outfd;
-
- #ifdef NETCONN
- if (netconn) {
- if (ttyfd < 0) return (-1);
- } else
- #endif /* NETCONN */
- if (ttyfdout < 0) return (-1);
-
- debug(F101,"ttol n","",n);
- tries = TTOLMAXT;
- len = n;
-
- while ((n > 0) && (tries-- > 0)) {
- debug(F101,"ttol try","",TTOLMAXT - tries);
- #ifdef NETCONN
- if (netconn)
- x = write(ttyfd,s,n);
- else
- #endif /* NETCONN */
- x = dgncoub(ttyfdout,s,n);
- if (x == n) {
- debug(F101,"ttol ok","",x);
- return(len);
- } else if (x < 0) {
- debug(F101,"ttol failed","",lasterror());
- return(-1);
- } else {
- debug(F101,"ttol partial","",x);
- s += x; /* update buffer address for next */
- n -= x; /* update length for next read */
- if (x > 0) msleep(100);
- }
- }
- return((n < 1) ? len : -1);
- }
-
-
- /* T T O C -- Output a character to the communication line */
- /*
- This function should only be used for interactive, character-mode operations,
- like terminal connection, script execution, dialer i/o, where the overhead
- of the signals and alarms does not create a bottleneck.
- */
-
- ttoc(c) char c; {
- int x,xx;
- #define TTOC_TMO 15
- c &= 0xff;
- /* debug(F101,"ttoc","",(CHAR) c); */
- #ifdef NETCONN
- if (netconn) {
- if (ttyfd < 0) return(-1);
- } else
- #endif /* NETCONN */
- if (ttyfdout < 0) return(-1); /* Not open. */
- saval = signal(SIGALRM,timerh);
- xx = alarm(TTOC_TMO);
- if (xx < 0) xx = 0; /* Save old alarm value. */
- if (setjmp(sjbuf)) {
- ttimoff();
- if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
- #ifdef NETCONN
- if (!netconn) {
- #endif /* NETCONN */
- /* debug(F100,"ttoc timeout","",0); */
- if (ttflow == FLO_XONX) {
- debug(F100,"ttoc flow","",ttflow);
- /* issue clear device */
- }
- #ifdef NETCONN
- }
- #endif /* NETCONN */
- return(-1);
- } else {
- #ifdef NETCONN
- if (netconn) /* use ttyfd for tcp connections */
- x = write(ttyfd,&c,1);
- else /* ttyfdout for local connections */
- #endif /* NETCONN */
- x = (dgncoub(ttyfdout,&c,1));
- if (x != 1) {
- ttimoff(); /* If error, turn off timer, */
- alarm(xx);
- debug(F101,"ttoc error x","",x);
- debug(F101,"ttoc last error","",lasterror());
- return (-1);
- }
- }
- ttimoff();
- alarm(xx);
- return (0);
- }
-
- /* T T I N L -- Read a record (up to break character) from comm line. */
- /*
- Reads up to "max" characters from the communication line, terminating on:
-
- (a) the packet length field if the "turn" argument is zero, or
- (b) on the packet-end character (eol) if the "turn" argument is nonzero
-
- and returns the number of characters read upon success, or if "max" was
- exceeded or the timeout interval expired before (a) or (b), returns -1.
-
- The characters that were input are copied into "dest" with their parity bits
- stripped if parity was selected. Returns the number of characters read.
- Characters after the eol are available upon the next call to this function.
-
- The idea is to minimize the number of system calls per packet, and also to
- minimize timeouts. This function is the inner loop of the program and must
- be as efficient as possible. The current strategy is to use myread().
-
- WARNING: this function calls parchk(), which is defined in another module.
- Normally, ckutio.c does not depend on code from any other module, but there
- is an exception in this case because all the other ck?tio.c modules also
- need to call parchk(), so it's better to have it defined in a common place.
- */
-
- /* ENH -- assume PARSENSE */
-
- #ifdef CTRLC
- #undef CTRLC
- #endif /* CTRLC */
- #define CTRLC '\03'
-
- int
- ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest,eol,start; {
- int pktlen = -1;
- int j;
- CHAR ch;
- int lplen = 0;
- int havelen = 0;
-
- if (ttyfd < 0) return(-1); /* Not open. */
- if (turn)
- debug(F101,"ttinl read until eol, turn","",turn);
- else
- debug(F101,"ttinl read packet-length characters, turn","",turn);
- debug(F101,"ttinl max","",max);
- debug(F101,"ttinl timo","",timo);
-
- *dest = '\0'; /* Clear destination buffer */
-
- if (timo < 0) timo = 0;
-
- if (timo) { /* Don't time out if timo == 0 */
- saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
- alarm(timo); /* Set it. */
- }
- if (setjmp(sjbuf)) { /* Timer went off? */
- debug(F100,"ttinl timout","",0); /* Get here on timeout. */
- debug(F110," with",(char *) dest,0);
- ttimoff(); /* Turn off timer */
- return(-1); /* and return error code. */
- } else {
- int i, m, n;
- int ccn = 0;
- int flag = 0;
-
- debug(F000,"ttinl start","",start);
- flag = 0; /* Start of packet flag */
-
- ttpmsk = m = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
-
- /* Now read into destination, stripping parity and looking for the */
- /* the packet terminator, and also for two Ctrl-C's typed in a row. */
-
- i = 0; /* Destination index */
- debug(F101,"ttinl eol","",eol);
- while (i < max-1) {
- /* debug(F101,"ttinl i","",i); */
- if ((n = myread()) < 0) {
- debug(F101,"ttinl myread failure, n","",n);
- debug(F101,"ttinl myread errno,","",errno);
- /* Don't let EINTR break packets. */
- if (n == -3 && errno == EINTR && i > 0) {
- debug(F101,"ttinl myread i","",i);
- continue;
- }
- break;
- }
- debug(F101,"ttinl char","", (n & ttpmsk));
- /*
- Figure out what the length is supposed to be in case the packet
- has no terminator (as with Honeywell GCOS-8 Kermit).
- */
- #ifndef xunchar
- #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
- #endif /* xunchar */
- if ((flag == 0) && ((n & 0x7f) == start)) flag = 1;
- if (flag) dest[i++] = n & ttpmsk;
- /*
- If we have not been instructed to wait for a turnaround character, we
- can go by the packet length field. If turn != 0, we must wait for the
- end of line (eol) character before returning.
- */
- if (i == 2) {
- pktlen = xunchar(dest[1]);
- havelen = (pktlen > 1);
- debug(F101,"ttinl length","",pktlen);
- } else if (i == 5 && pktlen == 0) {
- lplen = xunchar(dest[4]);
- } else if (i == 6 && pktlen == 0) {
- pktlen = lplen * 95 + xunchar(dest[5]) + 5;
- havelen = 1;
- debug(F101,"ttinl length","",pktlen);
- }
- if (xfrcan && ((n & 0x7f) == xfchr)) { /* Check cancellation */
- if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
- if (timo) { /* Clear timer. */
- ttimoff();
- }
- fprintf(stderr,"^C...\r\n"); /* Echo Ctrl-C */
- return(-2);
- }
- } else ccn = 0; /* Not ^C, so reset ^C counter, */
- if (flag == 0) {
- debug(F101,"ttinl skipping","",n);
- continue;
- }
-
- /* Check for end of packet */
-
- if (((n & 0x7f) == eol) || (!turn && havelen && (i > pktlen+1))) {
- if ((n & 0x7f) != eol) {
- debug(F101,"ttinl EOP length","",pktlen);
- debug(F101,"ttinl i","",i);
- } else debug(F101,"ttinl got eol","",eol);
- dest[i] = '\0'; /* Terminate the string, */
-
- /* Here's where we actually check and adjust the parity. */
- /* The major flaw here is if parity is NONE (ttprty = 0) and the packets */
- /* really do have no parity, then parchk() is called for every packet. */
- /* In practice, this doesn't really harm efficiency noticably, but it would */
- /* be better if ttinl() had a way of knowing to stop doing this once a */
- /* particular file transfer had been started and checked. */
- if (ttpflg++ == 0 && ttprty == 0) {
- if ((ttprty = parchk(dest,start,i)) > 0) {
- int j;
- debug(F101,"ttinl senses parity","",ttprty);
- debug(F110,"ttinl packet before",dest,0);
- ttpmsk = 0x7f;
- for (j = 0; j < i; j++)
- dest[j] &= 0x7f; /* Strip parity from packet */
- debug(F110,"ttinl packet after ",dest,0);
- } else debug(F101,"parchk","",ttprty);
- }
- if (timo) { /* Turn off timer. */
- ttimoff();
- }
- debug(F111,"ttinl got", dest,i);
- return(i);
- }
- } /* end of while() */
- ttimoff();
- return(-1);
- }
- }
-
- /* T T I N C -- Read a character from the communication line */
- /*
- On success, returns the character that was read, >= 0.
- On failure, returns -1 or other negative myread error code.
- */
-
- int
- ttinc(timo) int timo; {
- int n = 0;
- CHAR ch = 0;
-
- if (ttyfd < 0) return(-1); /* Not open. */
- if (timo <= 0) { /* Untimed. */
- /* comm line failure returns -1 thru myread, so no &= 0377 */
- n = myread(); /* Wait for a character... */
- /* debug(F101,"ttinc n","",n); */
- return(n < 0 ? n : n & ttpmsk);
- } else {
- int xx;
- saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
- xx = alarm(timo); /* calls because I'm getting errors */
- if (setjmp(sjbuf)) /* about these signal calls -- " the */
- n = -1; /* destination of a non-local GOTO is*/
- else { /* an inactive block" */
- n = myread(); /* If managing own buffer... */
- /* debug(F101,"ttinc myread","",n); */
- }
- ttimoff();
- #ifdef NETCONN
- if (netconn) {
- if (n == -2) { /* read() returns 0 */
- netclos(); /* on network read failure */
- netconn = 0; /* ENH - deleted errno = ENOTCON */
- }
- }
- #endif /* NETCONN */
- return( (n < 0) ? n : (n & ttpmsk) ); /* Return masked char or neg. */
- }
- }
-
- /* T T S N D B -- Send a BREAK signal */
-
- ttsndb() {
- int x; long n; char spd; /* In VS, the duration of the break */
- /* is until next write() or charac- */
- debug(F101,"ttsndb ttyfd","",ttyfd); /* teristics change */
- if (ttyfd < 0) return(-1); /* Not open. */
-
- #ifdef NETCONN
- if (netconn) /* Send network BREAK */
- return(netbreak());
- #endif /* NETCONN */
-
- #ifdef UXIII
- #ifdef datageneral
- if (sys_clrdv(channel(ttyfdout),1<<31,$CDSBRK)) { /* Send a BREAK */
- perror("Can't send BREAK");
- return(-1);
- }
- return(0);
- #endif
- #endif
- }
-
- /* T T S N D L B -- Send a "long" BREAK signal */
-
- ttsndlb() { /* In VS, they're long by default -- see ttsndb() */
- return(ttsndb());
- }
-
-
- /* M S L E E P -- Millisecond version of sleep(). */
-
- /*
- Intended only for small intervals. For big ones, just use sleep().
- */
-
- msleep(m) int m; {
-
- #ifdef UXIII
- #define CLOCK_TICK 17 /* 1/60 sec */
- extern long times();
- long t1, t2, tarray[4];
- int t3;
-
- if (m <= 0) return(0);
- if ((t1 = times(tarray)) < 0) return(-1);
- while (1) {
- if ((t2 = times(tarray)) < 0) return(-1);
- t3 = ((int)(t2 - t1)) * CLOCK_TICK;
- if (t3 > m) return(t3);
- }
- #endif
- }
-
-
- /* R T I M E R -- Reset elapsed time counter */
-
- rtimer() {
- tcount = time( (long *) 0 );
- }
-
-
- /* G T I M E R -- Get current value of elapsed time counter in seconds */
-
- gtimer() {
- int x;
- x = (int) (time( (long *) 0 ) - tcount);
- debug(F101,"gtimer","",x);
- /* rtimer(); */
- return( (x < 0) ? 0 : x );
- }
-
-
- /* Z T I M E -- Return date/time string */
-
- ztime(s) char **s; {
-
- #ifdef UXIII
- extern long time(); /* Sys III/V way to do it */
- char *ctime();
- long clock_storage;
-
- clock_storage = time( (long *) 0 );
- *s = ctime( &clock_storage );
- #endif
- }
-
-
- /* C O N G M -- Get console terminal modes. */
-
- /*
- Saves current console mode, and establishes variables for switching between
- current (presumably normal) mode and other modes.
- */
-
- congm() {
- if (backgrd || !isatty(0)) { /* only for real ttys */
- cgmf = -1;
- return (-1); /* it used to return a zero for this case */
- }
- ioctl(0,TCGETA,&ccold);
- ioctl(0,TCGETA,&cccbrk);
- ioctl(0,TCGETA,&ccraw);
- /* For DG, also get the tty extended device characteristics. */
- sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccold);
- sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccraw);
- sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccbrk);
- cgmf = 1; /* Flag that we got them. */
- }
-
-
-
- /* C O N C B -- Put console in cbreak mode. */
-
- /* Returns 0 if ok, -1 if not */
-
- concb(esc) char esc; {
- int x;
- debug(F101,"concb backgrd","",backgrd);
- if (!isatty(0)) return(0); /* only for real ttys */
- debug(F100,"concb isatty","",0);
- if (backgrd) return(0);
- if (cgmf == 0) congm(); /* Get modes if necessary. */
- escchr = esc; /* Make this available to other fns */
- ckxech = 1; /* Program can echo characters */
- #ifdef datageneral
- cccbrk.c_lflag |= CBREAK;
- #endif
- cccbrk.c_lflag &= ~(ICANON|ECHO);
- cccbrk.c_cc[0] = 003; /* interrupt char is control-c */
- cccbrk.c_cc[1] = escchr; /* escape during packet modes */
- cccbrk.c_cc[4] = 1;
- cccbrk.c_cc[5] = 1;
- x = ioctl(0,TCSETAW,&cccbrk); /* set new modes . */
- #ifdef datageneral
- if (sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccbrk))
- { perror("concb: gechr: "); return(-1); }
- #endif
- #ifndef NOSETBUF
- if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */
- #endif /* NOSETBUF */
- return(x);
- }
-
- /* C O N B I N -- Put console in binary mode */
-
- /* Returns 0 if ok, -1 if not */
-
- conbin(esc) char esc; {
- int filedes,filedes2;
-
- if (!isatty(0)) return(0); /* only for real ttys */
- if (cgmf == 0) congm(); /* Get modes if necessary. */
- escchr = esc; /* Make this available to other fns */
- ckxech = 1; /* Program can echo characters */
- ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
- ccraw.c_iflag |= (BRKINT|IGNPAR);
- ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
- |INPCK|ISTRIP);
- ccraw.c_oflag &= ~OPOST;
-
- /*** Kermit used to put the console in 8-bit raw mode, but some users have
- *** pointed out that this should not be done, since some sites actually
- *** use terminals with parity settings on their Unix systems, and if we
- *** override the current settings and stop doing parity, then their terminals
- *** will display blotches for characters whose parity is wrong. Therefore,
- *** the following two lines are commented out (Larry Afrin, Clemson U):
- ***
- *** ccraw.c_cflag &= ~(PARENB|CSIZE);
- *** ccraw.c_cflag |= (CS8|CREAD);
- ***
- *** Sys III/V sites that have trouble with this can restore these lines.
- ***/
- ccraw.c_cc[4] = 1;
- ccraw.c_cc[5] = 1;
- #ifdef datageneral
- if (ioctl(0,TCSETAW,&ccraw)) return(-1); /* set new modes . */
- if (sys_gechr( channel(0), (1<<31)|$CLMAX, ch_ccraw))
- { perror("conbin: gechr: "); return(-1); }
- return(0);
- #else
- return(ioctl(0,TCSETAW,&ccraw) ); /* set new modes . */
- #endif
- }
-
-
- /* C O N R E S -- Restore the console terminal */
-
- conres() {
- if (cgmf == 0) return(0); /* Don't do anything if modes */
- if (!isatty(0)) return(0); /* only for real ttys */
- #ifdef datageneral
- if (timocon)
- /* Timeouts are set, so un-set them. */
- resto(channel(0));
- #endif
- ckxech = 0; /* System should echo chars */
- #ifdef datageneral
- if (ioctl(0,TCSETAW,&ccold)) return(-1); /* set new modes . */
- if (sys_sechr( channel(0), (1<<31)|$CLMAX, ch_ccold))
- { perror("conres: sechr "); return(-1); }
- return(0);
- #else
- return(ioctl(0,TCSETAW,&ccold));
- #endif
- }
-
-
- /* C O N O C -- Output a character to the console terminal */
-
- conoc(c) char c; {
- write(1,&c,1);
- }
-
- /* C O N X O -- Write x characters to the console terminal */
-
- conxo(x,s) char *s; int x; {
- write(1,s,x);
- }
-
- /* C O N O L -- Write a line to the console terminal */
-
- conol(s) char *s; {
- int len;
- len = strlen(s);
- write(1,s,len);
- }
-
- /* C O N O L A -- Write an array of lines to the console terminal */
-
- conola(s) char *s[]; {
- int i;
- for (i=0 ; *s[i] ; i++) conol(s[i]);
- }
-
- /* C O N O L L -- Output a string followed by CRLF */
-
- conoll(s) char *s; {
- conol(s);
- write(1,"\r\n",2);
- }
-
-
- /* C O N C H K -- Return how many characters available at console */
-
- conchk() {
- int x; long n;
-
- if (!isatty(0)) return (0);
- #ifdef UXIII
- if (conesc) { /* Escape typed */
- conesc = 0;
- signal(SIGQUIT,esctrp); /* Restore escape */
- return(1);
- }
- return(0);
- #else
- #ifdef FIONREAD
- x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */
- return((x < 0) ? 0 : n);
- #else
- return(0); /* Others can't do. */
- #endif
- #endif
- }
-
-
- #ifdef datageneral
-
- /* D G N C O U B -- Output len characters to the file number filenum */
-
- dgncoub(filenum,chs,len) int filenum, len; char *chs;
- {
- int ac2,err;
-
- if (len == 0) return(0);
-
- if (filenum == ttyfdout) {
- xout_parms.ibad = chs;
- xout_parms.ircl = len;
- ac2 = &xout_parms;
- } else {
- w_io_parms.ich = channel(filenum);
- w_io_parms.ibad = chs;
- w_io_parms.ircl = len;
- ac2 = &w_io_parms;
- }
-
- if ((err = sys_write(ac2)) == 0)
- return(((P_NIO_EX *) ac2)->irlr); /* ENH - change to return length */
- if ( err != ERLTL && err != EREOF ) {
- perror("dgncoub: sys_write ");
- return(-err); /* ENH - change to return */
- } /* negative of error code */
- else return(((P_NIO_EX *) ac2)->irlr);
- }
-
-
- /* D G N C I N B -- System level read of len characters from file number
- fileno. The global DG i/o structures are used for this.
-
- Return codes: irlr if data read ok, where irlr=length of data
- -1 if EOF
- -2 if timeout occured
- -err if an AOS/VS error occured, where err is errno
- */
-
- dgncinb(filenum,chs,len)
- int filenum,len; char *chs;
- {
- int ac2, /* I/O parameter address block */
- err, /* Error from sys_read */
- irlr; /* Number of bytes read */
- int rbe; /* Ring buffer empty on ESGT read */
-
- if (filenum == ttyfd) {
- x_io_parms.ibad = chs;
- x_io_parms.ircl = len;
- ac2 = (P_NIO_EX *) &x_io_parms;
- err = sys_read(ac2);
- irlr = x_io_parms.irlr;
- if (err == 0) {
- return(irlr);
- }
- rbe = (x_io_parms.etsp == 0) ? 0 : (x_io_scrn.esfc & $ESBE);
- } else {
- r_io_parms.ich = channel(filenum);
- r_io_parms.ibad = chs;
- r_io_parms.ircl = len;
- ac2 = (P_NIO_EX *) &r_io_parms;
- err = sys_read(ac2);
- irlr = r_io_parms.irlr;
- if (err == 0) {
- return(irlr);
- }
- rbe = (r_io_parms.etsp == 0) ? 0 : (r_io_scrn.esfc & $ESBE);
- }
-
- if ((err != ERLTL) && (err != ERDTO) && (err != EREOF)) {
- /* NOT line-too-long, timeout, or EOF errors.
- * Don't print error when it is a data overrun.
- */
- if (err != EROVR) perror("dgncinb: sys_read error");
- return(-err);
- } else {
- /* If the system read buffer was empty when a screen management
- * packet was supplied, then there is a virtual EOF condition.
- * So we return an EOF flag in that case (rbe != 0).
- */
- if ((err == EREOF) || rbe) return(-1); /* EOF */
- if (err == ERDTO)
- if (irlr <= 0) /* if no data, */
- return (-2); /* return -2 */
- return(irlr); /* else chars read */
- }
- }
- #endif datageneral
-
- /* C O N I N C -- Get a character from the console */
-
- coninc(timo) int timo; {
- int n = 0; char ch;
-
- if (timo <= 0) { /* no timeout specified */
- while (1) {
- /* Binary input */
- n = dgncinb(0,&ch,1);
- if (n == 0) continue;
- if (n > 0)
- return(ch & 0377); /* Return the char if read */
- else {
- if (lasterror() == EINTR)
- if (conesc) { /* If by SIGQUIT, */
- conesc = 0; /* the conesc variable is set, */
- return(escchr); /* so return the escape character. */
- } else continue; /* By other signal, try again. */
- else if (n == -2) { /* won't happen unless ?STOM */
- debug(F101,"coninc got timeout ","",n); /* has happened */
- continue;
- } else if (n == -1) /* behind our back */
- debug(F101,"coninc got eof indication","",n);
- else if (n < -2) /* -n = VS error code */
- debug(F101,"coninc got AOS/VS error","",-n);
- return(-1);
- }
- }
- }
- saval = signal(SIGALRM,timerh); /* else timeout specified */
- alarm(timo);
- if (setjmp(sjbuf)) n = -2;
- else
- n = dgncinb(0, &ch, 1);
- ttimoff(); /* Turn off timer */
- if (n > 0) return(ch & 0377);
- else {
- debug(F101, "coninc(timo) n","",n);
- debug(F101, "coninc(timo) errno","",lasterror());
- if ((lasterror() == EINTR) && conesc != 0) {
- conesc = 0;
- return(escchr); /* User entered escape character. */
- } else if (n == -2) /* won't happen */
- debug(F101, "coninc got DEVICE timeout","",n);
- else if (n == -1)
- debug(F101,"coninc got eof indication","",n);
- else if (n < -2) /* -n = VS error code */
- debug(F101,"coninc got AOS/VS error","",-n);
- return(-1);
- }
-
-
- }
-
- /* C O N G K S -- Console Get Keyboard Scancode */
-
- #ifndef congks
- /*
- This function needs to be filled in with the various system-dependent
- system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
- keyboard scan code. For now, it's a dummy.
- */
- int
- congks(timo) int timo; {
- return(coninc(timo));
- }
- #endif /* congks */
-
-
- /* These security routines are here, but they're not used. There's no */
- /* need for them in the AOS/VS implementation. When they were here, */
- /* they caused superuser to be turned off when kermit was started with */
- /* it on. Seemed to cause problems instead of solve them. --ENH */
-
- int
- priv_ini() /* if superu is on, turn off */
- {
- int ac0,ac1,ac2,error;
-
- ac0 = ac1 = ac2 = 0;
-
- error = sys( $SUSER, &ac0, &ac1, &ac2 );
- if( ac0 == -1 ) /* if it's on... */
- priv_off(); /* turn it off */
-
- return 0;
- }
-
- int
- priv_on() /* turn superu on */
- {
- int ac0,ac1,ac2,error;
-
- ac0 = -1; /* turn it on */
- ac1 = ac2 = 0;
-
- error = sys( $SUSER, &ac0, &ac1, &ac2 );
- if( error != NULL )
- error = -1; /* an error */
-
- return error;
- }
-
- int
- priv_off()
- {
- int ac0,ac1,ac2;
-
- ac0 = 1; /* turn it off */
- ac1 = ac2 = 0;
-
- return sys( $SUSER, &ac0, &ac1, &ac2 );
- }
-
- int
- priv_can()
- {
- return priv_off();
- }
-
- int
- priv_chk()
- {
- return priv_off();
- }
-
- VOID
- ttimoff() { /* Turn off any timer interrupts */
- alarm(0);
- if (saval)
- signal(SIGALRM,saval);
- else
- signal(SIGALRM,SIG_DFL);
- saval = NULL;
- }
-
- /* Similarly, this ctrlc_chk() routine is here, but it's not used. */
-
- void
- ctrlc_chk(buffer,n) int *buffer; int n; {
- #nolist
- #include <ckcker.h>
- #list
- extern int local,what;
- int i;
- extern SIGTYP trap();
-
- debug(F101,"Entering ctrlc_chk -- number of chars in buf","",n);
- debug(F101,"ctrlc_chk local =","",local);
- debug(F101,"ctrlc_chk what =","",what);
- if (what == W_CONNECT) /* ignore ^C's in connect mode */
- return;
- if (what == W_NOTHING) /* don't know what's what here */
- return; /* so ignore ^C in case data */
- if ((!local) &&
- ((what == W_SEND) || (what == W_RECV) || (what == W_REMO)))
- return;
- for (i = 0; i < n; i++) /* otherwise it's W_SEND, W_RECV */
- /* or W_REMOTE in local mode or */
- /* W_COMMAND in either mode */
- if ((buffer[i] & 0177) == CTRLC) {
- debug (F101,"Got ^C...","",what);
- my_count = 0; /* clear out buffer */
- trap(what); /* call signal handler */
- }
- }
-